package leo.mystudy.executors;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;

/**
 * @author lichao email:lichao@witspring.com
 * @Description: 任务切分线程池
 * @Date 2018/4/23 19:11
 * @since Ver V0.0.1
 */
public class ForkJoinPoolTest {
    public static void main(String[] args) {
        new ForkJoinPoolTest().test();
    }

    public void test() {
        ForkJoinPool exec = new ForkJoinPool(3);
        MyRecursiveAction action = new MyRecursiveAction(564);
        exec.invoke(action);
        try {
            exec.awaitTermination(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        exec.shutdown();
    }

    public class MyRecursiveTask extends RecursiveTask<Integer> {
        private int workLoad = 0;

        MyRecursiveTask(int workLoad) {
            this.workLoad = workLoad;
        }

        @Override
        protected Integer compute() {
            if (this.workLoad > 16) {
                System.out.println("splitting workLoad:" + this.workLoad);
                List<MyRecursiveTask> subTasks = createSubTasks();
                subTasks.forEach(n -> n.fork());
                Integer result = 0;
                for (MyRecursiveTask myRecursiveTask : subTasks) {
                    result += myRecursiveTask.join();
                }
                return result;
            } else {
                return this.workLoad;
            }
        }

        private List<MyRecursiveTask> createSubTasks() {
            List<MyRecursiveTask> result = new ArrayList<>();
            int subSize = this.workLoad / 2;
            result.add(new MyRecursiveTask(subSize));
            result.add(new MyRecursiveTask(this.workLoad - subSize));
            return result;
        }
    }

    public class MyRecursiveAction extends RecursiveAction {
        private int workLoad = 0;

        MyRecursiveAction(int workLoad) {
            this.workLoad = workLoad;
        }

        @Override
        protected void compute() {
            if (this.workLoad > 16) {
                System.out.println("splitting workLoad:" + this.workLoad);
                List<MyRecursiveAction> subTasks = createSubTasks();
                subTasks.forEach(n -> n.fork());
            } else {
                System.out.println("doing workload myself:" + this.workLoad);
            }
        }

        private List<MyRecursiveAction> createSubTasks() {
            List<MyRecursiveAction> result = new ArrayList<>();
            int subSize = this.workLoad / 2;
            result.add(new MyRecursiveAction(subSize));
            result.add(new MyRecursiveAction(this.workLoad - subSize));
            return result;
        }
    }
}
